package com.ease.integration.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ease.common.util.Assertion;
import com.ease.common.util.Detect;
import com.ease.integration.context.vo.IntegrationServiceContext;
import com.ease.integration.converter.ArgumentObjectInterconverter;
import com.ease.integration.converter.IntegrationValueConverterFactory;
import com.ease.integration.definition.constant.IntegrationMessageTemplateReserveKey;
import com.ease.integration.definition.service.IntegrationServiceDefinitionManagementService;
import com.ease.integration.definition.vo.IntegrationServiceDefinition;
import com.ease.integration.message.RequestMessage;
import com.ease.integration.service.IntegrationService;
import com.ease.integration.service.IntegrationServiceDispatcher;

/**
 * 负责分派外部进来的请求
 * 
 * @author nathanleewei
 * 
 */
public class IntegrationWebServiceDispatcherImpl implements IntegrationServiceDispatcher {

	private static final transient Log log = LogFactory.getLog(IntegrationWebServiceDispatcherImpl.class);

	private IntegrationServiceDefinitionManagementService integrationServiceDefinitionManagementService;

	private IntegrationValueConverterFactory integrationValueConverterFactory;

	private Map<String, IntegrationService> integrationServices;

	public Map<String, Object> doService(String integrationServiceDefinitionKey, Map<String, Object> requestMap) {

		// 根据integrationServiceDefinitionKey取得入参template
		IntegrationServiceDefinition integrationServiceDefinition = integrationServiceDefinitionManagementService.getIntegrationServiceDefinitionByKey(integrationServiceDefinitionKey);
		Assertion.notNull(integrationServiceDefinition, "请求" + integrationServiceDefinitionKey + "找不到定义上下文");

		String xmlPartOfArguments = null; // FreeMarkerSupport.getInstance().processPath(integrationServiceDefinition.getRequestMessageDefinition().getArgumentAnnotationXmlTemplatePath(),
											// requestMap);

		String[] xmlArray = xmlPartOfArguments.split(IntegrationMessageTemplateReserveKey.ARGUMENTS_SPLITER);
		for (int i = 0; i < xmlArray.length; i++) {
			String xmlDocument = xmlArray[i];
			int idx = xmlDocument.indexOf("=<?xml");
			if (-1 < idx) {
				String key = xmlDocument.substring(0, idx);
				String xml = xmlDocument.substring(idx + 1);
				requestMap.put(IntegrationMessageTemplateReserveKey.XML_STRING + key, xml);
			}
		}

		requestMap.putAll(integrationValueConverterFactory.getConverters());

		// 生成RequestMessage对象
		RequestMessage requestMessage = (RequestMessage) ArgumentObjectInterconverter.parameterToObject(requestMap, integrationServiceDefinition.getRequestMessageDefinition()
				.getMessageXmlRepresentationTemplatePath(), integrationServiceDefinition.getRequestMessageDefinition().getMessageClass());

		IntegrationServiceContext integrationServiceContext = new IntegrationServiceContext();
		integrationServiceContext.setRequestMessage(requestMessage);
		integrationServiceContext.setServiceClass(integrationServiceDefinition.getIntegrationServiceBeanName());
		integrationServiceContext.setServiceMethod(integrationServiceDefinition.getIntegrationServiceBeanMethodName());

		/*
		 * 根据command取得出参template 根据template将出参转为返回结果
		 */
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			integrationServiceContext = doService(integrationServiceContext);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e, e);
			map.put(IntegrationMessageTemplateReserveKey.EXCEPTION_OBJECT, e);

			// IntegrationLog integrationLog =
			// IntegrationLogContext.getIntegrationLogContext
			// ().getIntegrationLog();
			// integrationLog.setIntegrationResult(IntegrationResultType.Failure)
			// ;
			// integrationLog.setErrorMessage(e.getMessage());
		}

		if (null != integrationServiceContext.getResponseMessage()) {
			map.put(IntegrationMessageTemplateReserveKey.INTEGRATION_VALUEOBJECT, integrationServiceContext.getResponseMessage());
		}
		map.putAll(integrationValueConverterFactory.getConverters());
		Map<String, Object> parameterMap = ArgumentObjectInterconverter.objectToParameters(map, integrationServiceDefinition.getResponseMessageDefinition()
				.getMessageArgumentRepresentationTemplatePath());

		if (log.isDebugEnabled()) {
			StringBuffer sb = new StringBuffer();
			sb.append("接口返回信息:\r\nintegrationServiceDefinitionKey: " + integrationServiceDefinitionKey + "\r\n");
			if (Detect.notEmpty(parameterMap)) {
				for (Map.Entry<String, Object> entry : parameterMap.entrySet()) {
					sb.append("arg[" + entry.getKey() + "]: " + entry.getValue() + "\r\n");
				}
			} else {
				sb.append("接口返回信息为空:\r\nintegrationServiceDefinitionKey: " + integrationServiceDefinitionKey + "\r\n");
			}
			log.debug(sb.toString());
		}

		return parameterMap;
	}

	// 调用Web Service
	public IntegrationServiceContext doService(IntegrationServiceContext integrationServiceContext) throws Exception {
		IntegrationService integrationService = integrationServices.get(integrationServiceContext.getServiceClass());
		Assertion.notNull(integrationService, integrationServiceContext.getServiceClass() + "无对应类对象");
		try {
			Method method = integrationService.getClass().getDeclaredMethod(integrationServiceContext.getServiceMethod(), new Class[] { IntegrationServiceContext.class });
			integrationServiceContext = (IntegrationServiceContext) method.invoke(integrationService, new Object[] { integrationServiceContext });
		} catch (InvocationTargetException e) {
			e.printStackTrace();
			throw new Exception(e.getTargetException());
		} catch (Exception e) {
			throw e;
		}
		return integrationServiceContext;
	}

	public Map<String, IntegrationService> getIntegrationServices() {
		return integrationServices;
	}

	public void setIntegrationServices(Map<String, IntegrationService> integrationServices) {
		this.integrationServices = integrationServices;
	}

	public IntegrationServiceDefinitionManagementService getIntegrationServiceDefinitionManagementService() {
		return integrationServiceDefinitionManagementService;
	}

	public void setIntegrationServiceDefinitionManagementService(IntegrationServiceDefinitionManagementService integrationServiceDefinitionManagementService) {
		this.integrationServiceDefinitionManagementService = integrationServiceDefinitionManagementService;
	}

	public IntegrationValueConverterFactory getIntegrationValueConverterFactory() {
		return integrationValueConverterFactory;
	}

	public void setIntegrationValueConverterFactory(IntegrationValueConverterFactory integrationValueConverterFactory) {
		this.integrationValueConverterFactory = integrationValueConverterFactory;
	}

}
